/***********************************************************************************
 @file   
 @author
 @attention 系统参数文件
 ***********************************************************************************/
#include "system.h"

/***********************************************************************************
 * @global 系统数据初始化 文件结尾有数据初始化内容 需要同步
***********************************************************************************/
_Data_store_struct system_data=
{
    .head=0XCC,
    .soft_version=SOFT_VERSION,
    .preheating_time=10,
    .unit=1,
    .precision=1,
    .gastype=2,
    .sensor_mode=1,
    .lora_strength=1,
    .alarm_times=3,
    .energy_flag=ENERGY_DISPLAY,
    .energy_full=ENERGY_FULL,
    .speak=1,                                           //0-加油站报警音，1-普通报警音

    .mobility=20,
    .angle_alarm=70,

    .low_alarm=20,
    .high_alarm=50,
    .range_ability=100,
    .zero=1550,
    .kuadu[0]=40,
    .adc[0]=1950,
    .myaddress = 1,
    .host_address[0]=1919,
    .hot_number=HOT_NUMBER,
    .data_stability = 5,//浓度变化小于5%不上传lora
    .speak_times    = 60,    //报警时间设定60-300s   
    #ifdef RESPONSE_FAST 
    .power_interval=500,
    #else
    .power_interval=5000,
    #endif
};
/***********************************************************************************
 * @para ADC类
***********************************************************************************/
uint16_t myadc[4];                                          //原始通道值
uint16_t adcdata;                                           //ADC采样的值
uint16_t adc_sensor; 
uint16_t mydata;
uint8_t  status;
int16_t  temperature;                                       //温度
uint8_t  humidity;   
uint16_t vbat;
uint8_t  energy;	    									//电池容量
uint8_t  power_low1;	    								//电池容量
uint8_t  power_low2;	    								//电池容量
uint8_t  power_long;
/***********************************************************************************
 * @para 其他
***********************************************************************************/
uint8_t goto_lowpower;
uint8_t start_averrage;
uint8_t dis_lowpower;
uint8_t notic_lowpower;
uint8_t perform_type;
uint8_t flag_perform_over;
uint8_t test_num;

int16_t  temporary_value_s16;
uint16_t temporary_value_u16;                                //临时值
uint16_t temporary_value_u16_1;                              //临时值1
uint32_t temporary_value_u32;                                //临时值2
int32_t  temporary_value_s32;                                //临时值2

uint8_t  data_change;                                        //数据变化
uint8_t  lora_ok;                                            //lora标识
uint8_t  xiaoyin;                                            //消音标志
uint8_t  gate_in;											 //密码入口
uint8_t  key;                                                //按键值
uint16_t password_in;                                        //临时值

uint8_t  ceshi;						 						 //测试状态
uint16_t preheating;										 //开机预热
uint8_t  startCount;										 //开始计时
/***********************************************************************************
 * @para 定时器类
***********************************************************************************/
uint16_t gzjs;									   //传感器脱落计时
uint8_t  activity;                                 //活动界面
uint16_t dead_time;                                //无操作时间计时
uint16_t dead_time_th = 1000;                      //无操作时间阈值

int64_t time_send_lora    = 15;                           //lora 发包倒计时
int64_t time_lora_config  = 15;                         //发送配置计时

uint16_t time_data_change;
uint16_t time_bg_on=TIME_BG_ON;

uint8_t  flag_adc_real;
uint16_t time_get_analog=TIME_ANALOG_PREHEAT;      //获取AD值
uint32_t time_attenuation=TIME_ATTENNUATION;       //衰减计时
uint32_t time_perform_wait;                        //执行等待时间

/***********************************************************************************
 * @brief  系统延时接口100us,移植后参数改为100us为单位
***********************************************************************************/
void delay_100us( uint32_t delay)
{
    delay100us(delay);
}
/***********************************************************************************
 * @brief  系统延时接口,移植后参数改为100us为单位
***********************************************************************************/
void delay_ms(uint32_t delay)
{
    delay1ms(delay);
}
/***********************************************************************************
 * @brief  系统喂狗接口  HAL_IWDG_Refresh(&hiwdg);
***********************************************************************************/
void system_wdg_refresh(void)
{
    Wdt_Feed();
}
/***********************************************************************************
 * @brief  系统adc接口
***********************************************************************************/
void system_adc_interface(void)
{
    if(adc_obj.chge_flag == 1)
    {
        adc_obj.chge_flag = 0;
         
        if(sensor_en_read==1)
        {
            myadc[0]=adc_obj.sensor_vol;    
            myadc[1]=(uint16_t)kalman_filter(adc_obj.opa_vol_res);
//            myadc[1]=adc_obj.opa_vol_res;
        }
        myadc[2]=adc_obj.bat_vol;
        myadc[3]=adc_obj.ref_vol; 
      // printf("vol:%d\r\n", myadc[1]); 
    }
}
/***********************************************************************************
 * @brief  系统定时器 间隔10ms
***********************************************************************************/
void system_timer(void)
{
    static uint8_t cece=0;
    //-----------------------------------开始界面
    if(preheating)
    {
        led_flicker();
        if(preheating%100==0)
        {
            lcd_dis_num2(system_data.myaddress,preheating/100);
            //显示预热界面参数
        }
        preheating--;
        if(preheating==0)
        {
            startCount=0;
        }
	}
    //-----------------------------------临时对话框返回时间计时
    if(return_time)
    {
        return_time--;
        if(return_time==0)
        {
            page_goto(return_page);
        }
    }

    //-----------------------------------测试界面倒计时
    if(status==6)
    {
        if(test_num)
        {
            if(cece>=100){
                test_num--;
                cece=0;
            }
            else{
                cece++;
            } 
            sleep_device_operation_time1(100);//留1s更新屏幕时间
        }
        else
        {
            status=0;
        }
    }
    //-----------------------------------空闲界面计时
    if(activity==1)
    {
        if(dead_time>dead_time_th)
        {
            dead_time=0;
            password_in=0;                
            page_goto(PAGE_DIS_MAIN);//前往主界面
        }
        else
            dead_time++;
    }
    else
        dead_time=0;
    //-----------------------------------
    #ifdef ANALOG_SENSOR
    system_adc_attenuation_timer(0);
    //-----------------------------------时间滤波 数据
    if(time_data_change)
    {
        time_data_change--;
    }
    #endif
}
/***********************************************************************************
 * @brief  设备启动初始化
***********************************************************************************/
void system_start(void)
{
    uint16_t crc_a,crc_b,ture_a=0,ture_b=0,ture_all=1;
    uint8_t i,j=0;
    _Data_store_struct data_a,data_b;
    uint8_t *data_ab=(uint8_t *)&data_a,*data_bb=(uint8_t *)&data_b; 
    while(j<5)
    {
        j++;
        delay1ms(300);
        flash_read(EEPROM_ADDR0,(uint8_t *)&data_a,sizeof(_Data_store_struct));
        flash_read(EEPROM_ADDR1,(uint8_t *)&data_b,sizeof(_Data_store_struct));
        {
             crc_a=GetCRC((uint8_t *)&data_a,sizeof(_Data_store_struct)-2);
             if((crc_a==data_a.crc)&&(data_a.head==0XCC)&&(data_a.soft_version==SOFT_VERSION))
             {
                 ture_a=1;
             }
             crc_b=GetCRC((uint8_t *)&data_b,sizeof(_Data_store_struct)-2);
             if((crc_b==data_b.crc)&&(data_b.head==0XCC)&&(data_b.soft_version==SOFT_VERSION))
             {
                 ture_b=1;
             }
             for(i=0;i<sizeof(_Data_store_struct);i++)
             {
                 if(data_ab[i]!=data_bb[i])
                 {
                     ture_all=0;
                 }
             }
             if((ture_all)&&(ture_a)&&(ture_b))
             {
                 ture_all=1;
             }
             else
             {
                 ture_all=0;
             }
         }
         if(ture_all)
         {
             memcpy(&system_data,&data_a,sizeof(_Data_store_struct));
         }
         else
         {
             if(ture_a)
             {
                 memcpy(&system_data,&data_a,sizeof(_Data_store_struct));
             }
             else if(ture_b)   
             {
                 memcpy(&system_data,&data_b,sizeof(_Data_store_struct));
             }
         }
         if((ture_all)||(ture_a)||(ture_b))
         {
             break;
         }
     }
     if(ture_all==0)
     {
         data_save();
     }
}
/***********************************************************************************
 * @brief  开机预热 KAIJI_Animation
***********************************************************************************/
void system_power_on(void)  
{
    preheating=(system_data.preheating_time)*100;
//    preheating=(2)*100;
 
	startCount=1; 
	while(preheating)
	{
        delay1ms(100);
        system_adc_preheat(); 
		system_wdg_refresh(); 
	}
    page_goto(PAGE_DIS_MAIN);
}
/***********************************************************************************
 * @brief  获取系统状态函数参数
***********************************************************************************/
uint8_t temp_energy[10];
uint8_t times_count=0;
uint8_t times_zero=0,times_low10=0,times_low5=0;
/***********************************************************************************
 * @brief  获取系统状态
 * @param  原程序参数   AIN0 传感器输入     myadc[0]  adc_obj.sensor_vol        
                        AIN1 运放输出       myadc[1]  adc_obj.opa_vol_f
                        AIN2 电池电压       myadc[2]  adc_obj.bat_vol
                        AIN3 内部基准电压   myadc[3]  null
***********************************************************************************/
void system_power_status(void)
{
    uint8_t i,max_energy=0,min_energy=255;
    uint16_t total_data=0;
    uint16_t energy_null=3200;
    
    
    if((alarm_en_read==0)&&(sleep_obj.sensor_cnt<RTC_WAKEUP_TIME/2))
    {
        goto here;  
    }
    else
    {
        return;
    }  
    
    here:
    system_adc_interface();
    vbat = (uint16_t)(1000.0*((float)myadc[2]/4095)*2.5*2.0);//2.5ref
//    printf("vbat=%d\r\n",vbat);   

    if(system_data.energy_full==3600)
    {
        energy_null=2800;// 设置空电阈值
    }
    // 根据当前电压计算电量百分比,线性插值计算电量百分比
    if(vbat<=energy_null)     //3.2V
        temp_energy[times_count]=0;
    else if(vbat>=system_data.energy_full)//
        temp_energy[times_count]=100;
    else
        temp_energy[times_count]=(vbat-energy_null)*100/(system_data.energy_full-energy_null);
   
    // 滑窗滤波 10次
    if(times_count<9)
    {
        times_count++;
    }
    else
    {
        times_count=0;
        start_averrage=1;
    }
    if(start_averrage)
    {
        for(i=0;i<10;i++)
        {
            if(temp_energy[i]>max_energy)
                max_energy=temp_energy[i];
            if(temp_energy[i]<min_energy)
                min_energy=temp_energy[i];
            total_data=total_data+temp_energy[i];
        }
        energy=(total_data-max_energy-min_energy)/8;
        
//        printf("energy=%d\r\n",energy);  
        //电量小于10%
        if(energy<10)
        {
            if(times_low10<TIMES_POWER_LOW10)
            {
                times_low10++;
            }
            else
            {
                power_low1=1;
            }
        }
        else
        {
            times_low10=0;
            power_low1=0;
        }
        if(energy<5)
        {
            if(times_low5<TIMES_POWER_LOW5)
            {
                times_low5++;
            }
            else
            {
                power_low2=1;
            }
        }
        else
        {
            times_low5=0;
            power_low2=0;
        }
        //电量 = 0
        if(energy==0)
        {
            if(times_zero<TIMES_POWER_ZERO)
            {
                times_zero++;
            }
            else
            {
                lora_send_message(1);//没电
                system_wdg_refresh();
                printf("device power off\r\n");
                delay1ms(2000);
                bat_en(0);
            }
        }
        else
        {
            times_zero=0;
        }
    }
}
/***********************************************************************************
 * @brief ad值更新  get_myadc  
 * @param 
***********************************************************************************/
void system_adc_update(void)
{
    uint8_t i;
    float vol,temp; 
     
    system_adc_interface();
//    vol  = 1.2f/(float)myadc[3]*myadc[1];//实际电压
//    adcdata     = vol/3.0*4096.0;//转化3V电压下ad值      
    adcdata       = myadc[1]*3.0f/2.5f;
    adc_sensor    = myadc[0];
    flag_adc_real = 1;   //数据处理flag

}
/***********************************************************************************
 * @brief 预热期间获取ad值  preheat_get_adc 尽快出电池电压
 * @param 
***********************************************************************************/
void system_adc_preheat(void)
{
    uint8_t i,max_energy=0,min_energy=255;
    uint16_t total_data=0;
    uint16_t energy_null=3200;
    
    system_adc_interface();   
    vbat = (uint16_t)(1200.0*((float)myadc[2]/(float)myadc[3])*2.0);
//    printf("preheat_bat_vol:%d\r\n",vbat);;

    if(system_data.energy_full==3600)
    {
        energy_null=3180;
    }  
    
    if(vbat<=energy_null)     //3.3V
        temp_energy[times_count]=0;
    else if(vbat>=system_data.energy_full)
        temp_energy[times_count]=100;
    else
        temp_energy[times_count]=(vbat-energy_null)*100/(system_data.energy_full-energy_null);
    if(times_count<9)
    {
        times_count++;
    }
    else
    {
        times_count=0;
        start_averrage=1;
    }
    //---------------------平均值滤波
    if(start_averrage)
    {
        for(i=0;i<10;i++)
        {
            if(temp_energy[i]>max_energy)
                max_energy=temp_energy[i];
            if(temp_energy[i]<min_energy)
                min_energy=temp_energy[i];
            total_data=total_data+temp_energy[i];
        }
        energy=(total_data-max_energy-min_energy)/8;
    }
}
/***********************************************************************************
 * @brief 数据处理流程,此函数在adc更新后运行
 * @param 
***********************************************************************************/
uint8_t alarm_times=0;
void system_data_process(void)
{
    #ifdef ANALOG_SENSOR
    uint16_t k;
    uint16_t myadcdata;
    if(time_attenuation==0)
    {
        time_attenuation=TIME_ATTENNUATION;
        system_adc_attenuation();
    }
    if(flag_adc_real && sensor_en_read)//转换完成，并且传感器在开的时候进行数据处理
    {
        flag_adc_real=0;
        myadcdata=adcdata;
        if(status!=6)
        {
            if(adc_sensor<ADC_SENSOR_L)
            {
                status=3;
            }
            else
            {
                if(status==3)
                {
                    status=0;
                }
            }
        }
        if(system_data.negative==0)
        {
            if((system_data.kuadu[2])&&(system_data.kuadu[1]))
            {
                if(myadcdata<=system_data.adc[0])
                {
                    if((myadcdata>=system_data.zero)&&(system_data.adc[0]>=system_data.zero))
                        k=(myadcdata-system_data.zero)*100/((system_data.adc[0]-system_data.zero)*100/system_data.kuadu[0]);
                    else
                        k=0;
                }
                else if(myadcdata<=system_data.adc[1])
                {
                    k=(myadcdata-system_data.adc[0])*100/((system_data.adc[1]-system_data.adc[0])*100/(system_data.kuadu[1]-system_data.kuadu[0]))+system_data.kuadu[0];
                }
                else 
                {
                    k=(myadcdata-system_data.adc[1])*100/((system_data.adc[2]-system_data.adc[1])*100/(system_data.kuadu[2]-system_data.kuadu[1]))+system_data.kuadu[1];
                }
            }
            else if(system_data.kuadu[1])
            {
                if(myadcdata<=system_data.adc[0])
                {
                    if((myadcdata>=system_data.zero)&&(system_data.adc[0]>=system_data.zero))
                        
                        k=(myadcdata-system_data.zero)*100/((system_data.adc[0]-system_data.zero)*100/system_data.kuadu[0]);
                    else
                        k=0;
                }
                else
                {
                    k=(myadcdata-system_data.adc[0])*100/((system_data.adc[1]-system_data.adc[0])*100/(system_data.kuadu[1]-system_data.kuadu[0]))+system_data.kuadu[0];
                }
            }
            else
            {
                if((myadcdata>=system_data.zero)&&(system_data.adc[0]>=system_data.zero))
                    k=(myadcdata-system_data.zero)*100/((system_data.adc[0]-system_data.zero)*100/system_data.kuadu[0]);
                else
                    k=0;
            }
        }
        else
        {
            if((system_data.kuadu[2])&&(system_data.kuadu[1]))
            {
                if(myadcdata>=system_data.adc[0])
                {
                    if((myadcdata<=system_data.zero)&&(system_data.adc[0]<=system_data.zero))
                        
                        k=(system_data.zero-myadcdata)*100/((system_data.zero-system_data.adc[0])*100/system_data.kuadu[0]);
                    else
                        k=0;
                }
                else if(myadcdata>=system_data.adc[1])
                {
                    k=(system_data.adc[0]-myadcdata)*100/((system_data.adc[0]-system_data.adc[1])*100/(system_data.kuadu[1]-system_data.kuadu[0]))+system_data.kuadu[0];
                }
                else 
                {
                    k=(system_data.adc[1]-myadcdata)*100/(system_data.adc[1]-(system_data.adc[2])*100/(system_data.kuadu[2]-system_data.kuadu[1]))+system_data.kuadu[1];
                }
            }
            else if(system_data.kuadu[1])
            {
                if(myadcdata>=system_data.adc[0])
                {
                    if((myadcdata<=system_data.zero)&&(system_data.adc[0]<=system_data.zero))
                        
                        k=(system_data.zero-myadcdata)*100/((system_data.zero-system_data.adc[0])*100/system_data.kuadu[0]);
                    else
                        k=0;
                }
                else
                {
                    k=(system_data.adc[0]-myadcdata)*100/((system_data.adc[0]-system_data.adc[1])*100/(system_data.kuadu[1]-system_data.kuadu[0]))+system_data.kuadu[0];
                }
            }
            else
            {
                if((myadcdata<=system_data.zero)&&(system_data.adc[0]<=system_data.zero))
                    k=(system_data.zero-myadcdata)*100/((system_data.zero-system_data.adc[0])*100/system_data.kuadu[0]);
                else
                    k=0;
            }
        }

        if(k>system_data.range_ability)
        {
            k=system_data.range_ability;
        }
//        if(k>=70)
//        {
//            time_overflow_wait=TIME_OVERFLOW_WAIT;
//        }
//        if(k<3)
//        {
//            k=0;
//        }
        if(((abs(k-mydata))>2)||(time_data_change==0))
        {
            mydata=k;
            time_data_change=TIME_DATA_CHANGE;
        }       
    }


    
    #endif
    if(status!=6)
	{
        if(mydata>=system_data.low_alarm)
        {
            if(alarm_times<system_data.alarm_times)
            {
                alarm_times++; 
            }
            if(alarm_times>=system_data.alarm_times)
            {
                if(mydata>=system_data.high_alarm)
                {
                     if(status!=3)
                        status=2;
                }
                else 
                {
                    if(status!=3)
                        status=1;
                 }
            }
        }
        else
        {
            alarm_times=0;
            if(status!=3)
                status=0;
            xiaoyin=0;//传感器恢复正常,取消报警
        }
    }
}
/***********************************************************************************
 * @global 进入睡眠时临时更新状态
***********************************************************************************/
void system_data_process_sleep(void)
{
    if(status!=6)
	{
        if(mydata>=system_data.low_alarm)
        {
            if(mydata>=system_data.high_alarm)
            {
                 if(status!=3)
                    status=2;
            }
            else 
            {
                if(status!=3)
                    status=1;
            }
        }
        else
        {
            if(status!=3)
                status=0;
            xiaoyin=0;//传感器恢复正常,取消报警
        }
    }
}
/***********************************************************************************
 * @global 数据保存
***********************************************************************************/
void data_save(void)
{   
    system_data.crc=GetCRC((uint8_t*)&system_data,sizeof(_Data_store_struct)-2);
    while(1)
    {
        delay1ms(10);
        __disable_irq();
        if(flash_write(EEPROM_ADDR0,(uint8_t *)&system_data.head,sizeof(_Data_store_struct))==Ok)
        {
            break;
        }
        __enable_irq();
    }
    __enable_irq();
    while(1)
    {
        delay1ms(10);
        __disable_irq();
        if(flash_write(EEPROM_ADDR1,(uint8_t *)&system_data.head,sizeof(_Data_store_struct))==Ok)
        {
            break;
        }
        __enable_irq();
    }
    __enable_irq();
}
#ifdef ANALOG_SENSOR
/***********************************************************************************
 * @brief adc衰减
***********************************************************************************/
void system_adc_attenuation(void)
{
    system_data.zero=adcdata+10;
    system_data.adc[0]=system_data.adc[0]*0.9988;
    system_data.adc[1]=system_data.adc[1]*0.9988;
    system_data.adc[2]=system_data.adc[2]*0.9988;
    data_save();
}

/***********************************************************************************
 * @brief adc衰减计时
***********************************************************************************/
void system_adc_attenuation_timer(uint8_t fun)
{
  switch (fun)
    {
    	case 0://普通定时器计时
            if(time_attenuation)
            {
                time_attenuation--;  
            }break;     
    	case 1://RTC计时
            if(time_attenuation)
            {
                time_attenuation -= rtc_xsec*100;
            }break;          
    	default:break;   		
    }
    if(time_attenuation<=2000)
    {
        time_attenuation = 0;
    }    
}
/***********************************************************************************
 * @brief 数据初始化
***********************************************************************************/
void data_save_init(void)
{
    _Data_store_struct system_data=
    {
        .head=0XCC,
        .soft_version=SOFT_VERSION,
        .preheating_time=10,
        .unit=1,
        .precision=1,
        .gastype=2,
        .sensor_mode=1,
        .lora_strength=1,
        .alarm_times=3,
        .energy_flag=ENERGY_DISPLAY,
        .energy_full=ENERGY_FULL,
        .speak=1,                                           //0-加油站报警音，1-普通报警音

        .mobility=20,
        .angle_alarm=70,

        .low_alarm=20,
        .high_alarm=50,
        .range_ability=100,
        .zero=1550,
        .kuadu[0]=40,
        .adc[0]=1950,
        .myaddress = 1,
        .host_address[0]=1919,
        .hot_number=HOT_NUMBER,
        .data_stability = 5,//浓度变化小于5%不上传lora
        
        #ifdef RESPONSE_FAST 
        .power_interval=500,
        #else
        .power_interval=5000,
        #endif
    };
    data_save();
}



#endif
